<?php
class Dp_Model 
{
	protected static $_properties = array();
	protected $_values = array();
	protected static $_modelName;
	protected $_mapper;

	public function __construct(array $options = null)
	{		
		if (is_array($options)) 
		{
			$this->setOptions($options);
		}
	}

	public static function setProperties($value)
	{
		static::$_properties = $value;
	}

	public static function getProperties()
	{
		return static::$_properties;
	}
	
	public function __set($name, $value)
	{
		$method = 'set' . $name;
		if (('mapper' == $name) || !method_exists($this, $method)) {
			throw new Exception("Invalid property $name");
		}
		$this->$method($value);
	}

	public function __get($name)
	{
		$method = 'get' . $name;
		if (('mapper' == $name) || !method_exists($this, $method)) {
			throw new Exception("Invalid property $name");
		}
		return $this->$method();
	}

	public function __call($method_name, $parameters)
	{		
		$properties = static::getProperties();
		
		if ('set' == substr($method_name, 0, 3))
		{
			$property = substr($method_name, 3);

			foreach ($properties as $key)
			{
				if (strcasecmp($property, $key) == 0)
				{					
					$this->_values[$key] = $parameters[0];
	
					return;
				}
			}
		}

		if ('get' == substr($method_name, 0, 3))
		{
			$property = substr($method_name, 3);
			foreach ($properties as $key)
			{
				if (strcasecmp($property, $key) == 0)
				{
						return $this->_values[$key];
				}
			}
		}

		throw new Exception("The program try to call an undefined function $method_name");
	}

	public function setOptions(array $options)
	{
		$methods = get_class_methods($this);
		foreach ($options as $key => $value) {
			$method = 'set' . ucfirst($key);
			if (in_array($method, $methods)) {
				$this->$method($value);
			}
		}
		return $this;
	}

	public function setMapper($mapper)
    {
        $this->_mapper = $mapper;
        return $this;
    }
 
    public function getMapper()
    {
        if (null === $this->_mapper) 
		{
			$mapper_name = static::getMapperName();
			$this->setMapper(new $mapper_name($mapper_name));
        }
        return $this->_mapper;
    }
 
	public static function getMapperName()
	{
		return str_replace('Model', 'Model_Mapper', static::$_modelName);
	}

    public function save()
    {
  		$this->getMapper()->save($this);
    }
 
    public function find($id)
    {
        $this->getMapper()->find($id, $this);
        return $this;
    }
 
    public function fetchAll($where = null, $order = null, $count = null, $offset = null)
    {
        return $this->getMapper()->fetchAll($where, $order, $count, $offset);
    }	
}
